package JVM;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.WeakHashMap;
import java.util.concurrent.TimeUnit;

/**
 * 强引用软引用弱引用虚引用
 * 强引用:就算出现OOM也不会进行垃圾回收
 * 软引用:内存不足才回收
 * 弱引用:只要GC就回收
 * 虚引用:形同虚设  必须和引用队列(ReferencesQueue)联合使用
 *       主要作用:跟踪对象被垃圾回收的状态
 *              仅仅提供了一种确保对象被finalize以后做的某些事情的机制
 *        get方法总是NULL
 */

public class 强软弱虚4种应用 {
    public static void main(String[] args) {

//        SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
        PhantomReferenceDemo();

    }
    private static void PhantomReferenceDemo() {
        List o1=new ArrayList();
        o1.add(5);
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();//引用队列  在被GC垃圾回收后会有值
        WeakReference<Object> weakReference=new WeakReference<>(o1,referenceQueue);//弱引用
        PhantomReference<Object> phantomReference=new PhantomReference<>(o1,referenceQueue);//虚引用
        System.out.println(o1);//5
        System.out.println(weakReference.get());//5   弱引用   gc才会收
        System.out.println(phantomReference.get());//null   虚引用
        System.out.println(referenceQueue.poll());//null
        System.out.println("================");
        o1=null;//置为空
        System.gc();//垃圾回收
        try{TimeUnit.MILLISECONDS.sleep(100);}catch (InterruptedException e){ e.printStackTrace();}

        System.out.println(o1);//null
        System.out.println(weakReference.get());//null   弱引用 gc直接回收
        System.out.println(phantomReference.get());//null    虚引用 一直为空
        System.out.println(referenceQueue.poll());
        //java.lang.ref.WeakReference@66d3c617    垃圾回收将 弱引用的东西放入ReferenceQueue引用队列里
        System.out.println(referenceQueue.poll());
        //java.lang.ref.PhantomReference@63947c6b  垃圾回收将 虚引用放入ReferenceQueue引用队列里
        System.out.println(referenceQueue.poll());//null    只放入了两个
    } //虚引用

    private static void WeakHashMapDemo() {

        System.out.println("=========HashMap============");
        HashMap<Integer,String> map=new HashMap<>();
        Integer key1 = new Integer(1);
        String value1 = "HashMap";
        map.put(key1,value1);
        System.out.println(map);
        key1=null;
        System.out.println(map);
        System.gc();
        System.out.println(map);

        System.out.println("=========WeakHashMap============");
        WeakHashMap<Integer,String> weakHashMap=new WeakHashMap<>();
        Integer key2 = new Integer(1);

        String  value2 = "WeakHashMap";
        weakHashMap.put(key2,value2);
        System.gc();
        System.out.println(weakHashMap);
        key2=null;
        System.out.println(weakHashMap);
        System.gc();
        System.out.println(weakHashMap);
    }    //弱引用 GC直接回收
    private static void WeakReferenceDemo() {
        Object o1=new Object();
        WeakReference<Object> weakReference=new WeakReference<>(o1);
        System.out.println(o1);
        System.out.println(weakReference.get());
        o1=null;
        System.gc();
        System.out.println("================");
        System.out.println(o1);
        System.out.println(weakReference.get());//不管内存够不够  直接回收为空
    }  //弱引用 GC直接回收

    private static void SoftReference_Enough(){
        /**
         * 软引用在内存足的时候不回收
         */
        Object o1=new Object();
        SoftReference<Object> softReference=new SoftReference<>(o1);
        System.out.println(o1);
        System.out.println(softReference.get());
        o1=null;
        System.gc();
        System.out.println(o1);
        System.out.println(softReference.get());
    } //软引用在内存足的时候不回收
    private static void SoftReference_NotEnough() {
        /**
         * -Xms5m -Xmx5m -XX:+PrintGCDetails
         */
        Object o1=new Object();
        SoftReference<Object> softReference=new SoftReference<>(o1);
        System.out.println(o1);
        System.out.println(softReference.get());
        o1=null;
        System.gc();
        try {
            byte[] bytes=new byte[30*1024*1024];
        }catch (Throwable e){
            e.printStackTrace();
        }finally {
            System.out.println(o1);
            System.out.println(softReference.get());//如果内存不足  也会输出null
        }


    } //软引用在内存不足的时候回收

    private static void ReferenceDemo() {
        Object obj1=new Object();
        Object obj2=obj1;
        System.out.println(obj1);
        obj1=null;
        System.gc();
        System.out.println(obj1);//null
        System.out.println(obj2);//不影响
    }  //强引用

}
